package com.mworld.galaxy.bull.service.product;

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springside.modules.persistence.DynamicSpecifications;
import org.springside.modules.persistence.SearchFilter;
import org.springside.modules.persistence.SearchFilter.Operator;

import com.mworld.galaxy.bull.entity.StatefulIdEntity;
import com.mworld.galaxy.bull.entity.product.Product;
import com.mworld.galaxy.bull.repository.product.ProductDao;

@Component
@Transactional(readOnly = true)
public class ProductService {

    @Autowired
    private ProductDao productDao;

    public Product getProduct(Long id) {
        return productDao.findOne(id);
    }

    public Product getProduct(String id) {
        try {
            return getProduct(Long.parseLong(id));
        } catch (Exception err) {
            return null;
        }
    }

    public Page<Product> searchProduct(Long shopId, Long categoryId, String title, double minPrice, double maxPrice,
            int pageNumber, int pageSize) {
        PageRequest pageRequest = new PageRequest(pageNumber - 1, pageSize, new Sort(Direction.DESC, "order"));
        Map<String, SearchFilter> filters = new HashMap<String, SearchFilter>();
        filters.put("shop.id", new SearchFilter("shop.id", Operator.EQ, shopId));
        if (categoryId != null && categoryId > 0) {
            filters.put("pk.category.id", new SearchFilter("pk.category.id", Operator.EQ, categoryId));
        }
        if (title != null && !title.isEmpty()) {
            filters.put("title", new SearchFilter("title", Operator.LIKE, title));
        }
        if (minPrice >= 0) {
            filters.put("price.min", new SearchFilter("price.min", Operator.GTE, minPrice));
        }
        if (maxPrice >= 0) {
            filters.put("price.max", new SearchFilter("price.max", Operator.LTE, maxPrice));
        }
        Specification<Product> spec = DynamicSpecifications.bySearchFilter(filters.values(), Product.class);
        return productDao.findAll(spec, pageRequest);
    }

    @Transactional(readOnly = false)
    public void saveProduct(Product product) {
        productDao.save(product);
    }

    @Transactional(readOnly = false)
    public void deleteProduct(Long id) {
        productDao.changeStatus(id, StatefulIdEntity.STATUS_DELETED);
    }

    @Transactional(readOnly = false)
    public void unDeleteProduct(Long id) {
        productDao.changeStatus(id, StatefulIdEntity.STATUS_ENABLED);
    }

    public Page<Product> searchProduct(Long shopId, Map<String, Object> searchParams, int pageNumber, int pageSize,
            String sortType) {
        PageRequest pageRequest = buildPageRequest(pageNumber, pageSize, sortType);
        Specification<Product> spec = buildSpecification(shopId, searchParams);

        return productDao.findAll(spec, pageRequest);
    }

    /**
     * 创建分页请求.
     */
    private PageRequest buildPageRequest(int pageNumber, int pagzSize, String sortType) {
        Sort sort = null;
        if ("auto".equals(sortType)) {
            sort = new Sort(Direction.DESC, "order");
        } else if ("title".equals(sortType)) {
            sort = new Sort(Direction.ASC, "title");
        }

        return new PageRequest(pageNumber - 1, pagzSize, sort);
    }

    /**
     * 创建动态查询条件组合.
     */
    private Specification<Product> buildSpecification(Long shopId, Map<String, Object> searchParams) {
        Map<String, SearchFilter> filters = SearchFilter.parse(searchParams);
        filters.put("shop.id", new SearchFilter("shop.id", Operator.EQ, shopId));
        Specification<Product> spec = DynamicSpecifications.bySearchFilter(filters.values(), Product.class);
        return spec;
    }
}
